home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / C / Comet2.1.3.cpt / Comet / emcursor.c < prev    next >
Text File  |  1991-10-31  |  35KB  |  1,449 lines

  1. /*
  2.     Copyright Cornell University 1986.  All rights are reserved.
  3.  
  4.     emcursor.c routines handle tracking and clicking of the mouse. 
  5.  
  6.     Buttons on the left side of the emulator are highlighted as the
  7.     mouse moves over them, and flash when clicked; pointing the mouse
  8.     at the '?' produces a list of button titles.  Care has to be taken
  9.     that emulator drawing is then disabled or clipped, depending on the 
  10.     drawing mode (direct or QuickDraw).
  11.     
  12.     While the mouse is within in the emulator screen area,
  13.     the character at which the mouse points is underlined.
  14.     
  15.     Clicking on the "Shrink control" causes the whole window to shrink
  16.     to icon size.
  17.     
  18.     Moire unfortunately does not post updateEvents before clearing the 
  19.     screen and returning control to the application, so
  20.     updatewait() fails to prevent the dropping of little mouse turds.
  21.     
  22. */
  23.  
  24. #include    <em.h>
  25.  
  26. #include    <cntldefs.h>
  27. #include    <rcodes.h>
  28. #include    <h19.h>
  29. #include    <3270.h>
  30. #include    <macdefs.h>
  31.  
  32. #define TOPRMARG    438                /* don't allow top controls past this point */
  33.  
  34. int wasinq2;
  35. int wasinq3;
  36. Point mouseloc;
  37.  
  38. short labelshift;                /* displaying 1-12 or 13-24? */
  39.  
  40. short q3button;                    /* the q3 control that is highlighted */
  41. Rect q3highrect;                /* highlighted rectangle of q3 control */
  42.  
  43. GrafPtr q3labdrawn;                /* q3 labels have been put up in this window */
  44. extern EventRecord myEvent;
  45. extern Rect q3highrect;
  46.  
  47. /*
  48.  * set cursor to different pointers and fiddle with buttons
  49.  *     and cursor tracking
  50.  */
  51.  
  52. #define NOWHERE    0
  53. #define INQ2    1
  54. #define INQ3    2
  55. #define INEMSCR 3
  56.  
  57.  
  58. maccursor(donttrack)
  59. short donttrack;        /* don't track the cursor */
  60. {
  61.     int where;
  62.     WindowPtr frontwind;
  63.     
  64.     if (keywindow == NULL || mfbackground) {
  65.         return;
  66.     }
  67.     frontwind = FrontWindow();
  68.     
  69.     where = NOWHERE;
  70.     if (frontwind == keydp->textwindow) {
  71.         extern CursHandle textcursor;
  72.         
  73.         SetPort(frontwind);
  74.         GetMouse(&mouseloc);
  75.         if (PtInRect(pass(mouseloc), &(*keydp->texthand)->viewRect) ) 
  76.             SetCursor(*textcursor);
  77.         else
  78.             SetCursor(&arrow);
  79.             
  80.         if (cupdatewait(keydp)) {
  81.             /* do nothing with the cursor */
  82.             return;
  83.         }
  84.         SetPort(keydp->emwindow);            /* set port so old highlights can be reset */
  85.     }
  86.     else if (frontwind == keydp->emwindow) {
  87.         /* the emulator window is up */
  88.         if (cupdatewait(keydp)) {
  89.             /* do nothing with the cursor */
  90.             return;
  91.         }
  92.     
  93.         SetPort(frontwind);
  94.         GetMouse(&mouseloc);
  95.             
  96.         if ( ((mouseloc.v > 0) && (mouseloc.v < keydp->bottommarg)) 
  97.                 && ((mouseloc.h > 0) && (mouseloc.h < keydp->rightmarg) )) {
  98.             /* in em screen, do cursor tracking */
  99.             where = INEMSCR;
  100.             if (!bkrd_act) {
  101.                 if (keydp->notrackcurs) {
  102.                     /* do no cursor tracking, make sure mouse cursor blanked */
  103.                     where = NOWHERE;
  104.                     SetCursor(&arrow);
  105.                 }
  106.                 else {
  107.                     SetCursor(thecursor);
  108.                     if (!donttrack) {
  109.                         trackon = emcurstrack(&mouseloc);
  110.                     }
  111.                 }
  112.             }
  113.         }
  114.         else {
  115. #ifdef WORONACURSOR
  116.             if (!donttrack && mouseloc.h > -12 && mouseloc.h <= 0) {
  117. #else
  118.             if (!donttrack && mouseloc.h > -12 && mouseloc.h < -3) {
  119. #endif
  120.                 KeyMap keyarray;
  121.                 short shift;
  122.                 
  123.                 keyarray[1] = 0;    /* make sure it's clear */
  124.                 
  125.                 GetKeys(&keyarray);
  126.                 shift = keyarray[1] & 0x00000001L ? 12 : 0;
  127.                     /* the shift key is down, do 13-24 */
  128.                 
  129.                 if (mouseloc.v >= -5 && mouseloc.v < frontwind->portRect.bottom) {
  130.                     /* in quadrant 3, 12 controls exist to be highlighted */
  131. #ifndef WORONACURSOR
  132.                     SetCursor(&arrow);
  133. #endif
  134.                     check3controls(pass(mouseloc), shift);
  135.                     wasinq3 = TRUE;
  136.                     where = INQ3;
  137.                     if (q3labdrawn)
  138.                         /* make sure Shift key changes get attention */
  139.                         q3labels(shift);
  140.                     labelshift = shift;
  141.                 }
  142.                 else if (mouseloc.v > -29 && mouseloc.v < -5) {
  143.                     /* in the question mark box, draw the labels */
  144.     
  145.                     where = INQ2;
  146.                     SetCursor(&arrow);
  147.                     if (!bkrd_act || q3labdrawn) {
  148.                         q3labels(shift);
  149.                         wasinq2 = TRUE;
  150.                     }
  151.                     labelshift = shift;
  152.                 }
  153.                 else 
  154.                     SetCursor(&arrow);
  155.  
  156.             }
  157.             else 
  158.                 SetCursor(&arrow);
  159.         }
  160.     }
  161.     
  162.     /* now reset the old mode that was on previously, but NOT the current one */
  163.     switch (where) {
  164.         case NOWHERE: {
  165.             if (trackon && !donttrack) {
  166.                 trackon = FALSE;
  167.                 InvertRect(&mouserect);
  168.             }
  169.             if (wasinq2) {
  170.                 wasinq2 = FALSE;
  171.                 blanklabels();
  172.             }
  173.             if (wasinq3) {
  174.                 wasinq3 = FALSE;
  175.                 reset3controls();
  176.             }
  177.             break;
  178.         }
  179.         case INQ2: {
  180.             if (trackon && !donttrack) {
  181.                 trackon = FALSE;
  182.                 InvertRect(&mouserect);
  183.             }
  184.             if (wasinq3) {
  185.                 wasinq3 = FALSE;
  186.                 reset3controls();
  187.             }
  188.             break;
  189.         }
  190.         case INQ3: {
  191.             if (trackon && !donttrack) {
  192.                 trackon = FALSE;
  193.                 InvertRect(&mouserect);
  194.             }
  195. #ifdef NOLABELHANG
  196.             /* erase labels when cursor in quadrant 3 button array */
  197.             if (wasinq2) {
  198.                 wasinq2 = FALSE;
  199.                 blanklabels();
  200.             }
  201. #endif
  202.             break;
  203.         }
  204.         case INEMSCR: {
  205.             if (wasinq2) {
  206.                 wasinq2 = FALSE;
  207.                 blanklabels();
  208.             }
  209.             if (wasinq3) {
  210.                 wasinq3 = FALSE;
  211.                 reset3controls();
  212.             }
  213.             break;
  214.         }
  215.     }
  216. }
  217.  
  218.  
  219. /* 
  220.  * Underline the character pointed to by the mouse cursor if there has 
  221.  * been a change in the mouse coordinates.
  222.  * Return TRUE if the underline is on the screen,  FALSE if not.
  223.  *
  224.  */
  225.  
  226. emcurstrack(mouseloc)
  227. Point * mouseloc;
  228. {
  229.     static Rect omouserect;        
  230.     static Point omouseloc;
  231.  
  232.     if ((mouseloc->v == omouseloc.v) && (mouseloc->h == omouseloc.h
  233.             || keydp->lineheight == 0 || keydp->fontwidth == 0) ) {
  234.         /* no change in mouse position or window not OK, do nothing */
  235.         if (trackon)
  236.             return(TRUE);
  237.         else
  238.             return(FALSE);
  239.     }
  240.  
  241.     omouseloc.v = mouseloc->v;
  242.     omouseloc.h = mouseloc->h;
  243.  
  244.     mouserect.top = mouseloc->v - (mouseloc->v % keydp->lineheight) + keydp->mrecttop + keydp->voffset;
  245.     mouserect.left = mouseloc->h - (mouseloc->h % keydp->fontwidth) + keydp->hoffset;
  246.  
  247.     if (trackon && 
  248.             (mouserect.top == omouserect.top)
  249.                 && (mouserect.left == omouserect.left) )
  250.         /* no change in x,y, no need to redraw highlight, do nothing */
  251.         return TRUE;
  252.  
  253.     mouserect.bottom = mouserect.top + keydp->mrectbot;
  254.     mouserect.right = mouserect.left + keydp->fontwidth;
  255.  
  256.     if (trackon) 
  257.         InvertRect(&omouserect);    /* blank old */
  258.     InvertRect(&mouserect);        /* set new */
  259.  
  260.     omouserect.top = mouserect.top;
  261.     omouserect.left = mouserect.left;
  262.     omouserect.bottom = mouserect.bottom;
  263.     omouserect.right = mouserect.right;
  264.     return(TRUE);
  265. }
  266.  
  267.  
  268. /* handle a mouse click in the emulator window */
  269.  
  270. emmouseclick(where)
  271. Point * where;
  272. {
  273.     /* otherwise we look for controls in the emulator window */
  274.     
  275.     if (cupdatewait(keydp)) {
  276.         /* do nothing */
  277.         return;
  278.     }
  279.  
  280.     if (where->v < 0) {
  281.         if (where->h > 0) {
  282.             /* in quadrant 1, top buttons */
  283.             if (!line25on(keydp))
  284.                 doq1controls(where);
  285.         }
  286.     }
  287.     else if (where->v > 0) {
  288.         if (where->h < 0) {
  289.             /* in quadrant 3, 12 buttons, send string assoc. w/ button */
  290.             doq3controls();
  291.         }
  292.         else if ( (where->h > 0)  && (where->h < keydp->rightmarg) ) {
  293.             /* in quadrant 4, h19 screen, do cursor motion for user */
  294.             if (!keydp->notrackcurs) {
  295.                 h19curset();
  296.             }
  297.         }
  298.         else {
  299.             /* maybe the user is hitting the shrink button */
  300.             if (PtInRect(pass(*where), &keydp->shrinkrect)) {
  301.                 int shrinkhigh;
  302.                 Rect shrect;
  303.                 Point shrinkmouse;
  304.                 
  305.                 shrect = keydp->shrinkrect;
  306.                 InsetRect(&shrect, -1, -1);
  307.                 InvertRect(&shrect);
  308.                 shrinkhigh = TRUE;
  309.                 while (StillDown()) {
  310.                     /* track the mouse until it goes up */
  311.                     GetMouse(&shrinkmouse);
  312.                     if (PtInRect(pass(shrinkmouse), &keydp->shrinkrect)) {
  313.                         if (!shrinkhigh) {
  314.                             shrinkhigh = TRUE;
  315.                             InvertRect(&shrect);
  316.                         }
  317.                     }
  318.                     else {
  319.                         if (shrinkhigh) {
  320.                             shrinkhigh = FALSE;
  321.                             InvertRect(&shrect);
  322.                         }
  323.                     }
  324.                 }
  325.                 if (shrinkhigh) {
  326.                     /* hide the emulator window, show the iconwindow */
  327.                     InvertRect(&shrect);
  328.                     shrinkwindow(keydp);
  329.                 }
  330.                 /* else just ignore */
  331.             }
  332.         }
  333.     }
  334. }
  335.  
  336. /*    get controls for the 3rd & 4th quadrant from resources 
  337.     and incorporate them in dynamically allocated strings 
  338.  
  339.     untyped controls = 0 - 127
  340.     ASCII resource numbers = 128 - 255
  341.     IBM resource numbers = 256 ->
  342. */
  343.  
  344.  
  345. controlinit(windptr, idnum)
  346. WindowPtr windptr;
  347. int idnum;            /* first of 11 Control ID numbers */
  348. {
  349.     ControlHandle * conptr;
  350.     ControlHandle * conend;
  351.     int lastright;
  352.     
  353.     /* height and skip size for the quadrant 3 controls */
  354.     q3conth = 22;
  355.     q3contskip = 7;
  356.     
  357.     if (idnum == 0)
  358.         return;
  359.     lastright = -3;
  360.     conend = &emdp->q1controls[Q1BUTMAX];
  361.     for (conptr = emdp->q1controls; conptr < conend; conptr++, idnum++) {
  362.         if ( (*conptr = GetNewControl(idnum, windptr) ) == NULL)
  363.             /* no control in resource */
  364.             break;
  365.  
  366.         /* resize the controls so the text inside just fits */
  367.         (**conptr)->contrlRect.left = lastright + 5;
  368.     
  369.         lastright = (**conptr)->contrlRect.right = (**conptr)->contrlRect.left +
  370.             (**conptr)->contrlTitle.length * 6 + 8;
  371.         if (lastright > TOPRMARG) {
  372.             DisposeControl(*conptr);
  373.             *conptr = NULL;
  374.             break;
  375.         }
  376.         (**conptr)->contrlVis = TRUE;
  377.     }
  378.     emdp->controlschanged = TRUE;
  379.     InvalRect(&emdp->toprect);
  380. }
  381.  
  382.  
  383. /* kills all controls in window, preventing drawing of blank controls */
  384.  
  385. killcontrols(contwind)
  386. WindowPtr contwind;
  387. {
  388.     Rect norect;
  389.     RgnHandle oldclip;
  390.  
  391.     /* reset clip closed */
  392.     oldclip = NewRgn();
  393.     GetClip(oldclip);
  394.     norect.top = 0;
  395.     norect.left = 0;
  396.     norect.bottom = 0;
  397.     norect.right = 0;
  398.     ClipRect(&norect);
  399.  
  400.     /* WARNING -- this kills ALL controls */
  401.     KillControls(contwind);
  402.  
  403.     /* reset clip to its former value */
  404.     SetClip(oldclip);
  405.     DisposeRgn(oldclip);
  406. }
  407.  
  408.  
  409. hideq1controls()
  410. {
  411.     ControlHandle * conptr;
  412.  
  413.     for (conptr = keydp->q1controls; *conptr != NULL; conptr++)
  414.         HideControl(*conptr);
  415. }
  416.  
  417.  
  418.  
  419. showq1controls()
  420. {
  421.     ControlHandle * conptr;
  422.  
  423.     for (conptr = keydp->q1controls; *conptr != NULL; conptr++)
  424.         ShowControl(*conptr);
  425. }
  426.  
  427.  
  428. /* 
  429.  * This routine either makes a selection range (if the mouse moves while it's
  430.  * down) or finds the x,y location of the last cursor tracking rectangle 
  431.  * & issues cursor motion commands to get there.
  432.  */
  433.  
  434. h19curset()
  435. {
  436.     int xloc;                /* first click x location */
  437.     int yloc;                /* " for y */
  438.     int nxloc;
  439.     int nyloc;
  440.     int oxloc;
  441.     int oyloc;
  442.     Point newmouse;
  443.     int nomove = TRUE;
  444.     long starttick;
  445.     Boolean donttrack;
  446.     
  447.     if (keydp->lineheight == 0 || keydp->fontwidth == 0) {
  448.         /* no divides / 0, please...*/
  449.         return;
  450.     }
  451.  
  452.     oyloc = yloc = mouserect.top / keydp->lineheight;
  453.     oxloc = xloc = mouserect.left / keydp->fontwidth;
  454.  
  455.     keydp->selfirsttime = TRUE;
  456.  
  457.     donttrack = cupdatewait(keydp);
  458.     
  459.     if (doubleclick) {
  460.         /* was embedded in "nomove" case, here it will be livelier */
  461.         
  462.         if (keydp->clickmacro != NULL) {
  463.             /* if there's a macro defined for a double click, do it */
  464.             struct token * tkptr;
  465.             int actcount;
  466.             
  467.             /* add the macro acts to the action queue */
  468.             HLock(keydp->clickmacro);
  469.             
  470.             tkptr = (struct token *) (*keydp->clickmacro + 4);
  471.             actcount = (GetHandleSize(keydp->clickmacro) - 4) / 2;
  472.             
  473.             while (actcount-- > 0) {
  474.                 keyputaction(tkptr->class, tkptr->entry);
  475.                 tkptr++;
  476.             }
  477.             
  478.             HUnlock(keydp->clickmacro);
  479.             
  480.             bkrd_token_service();        /* execute the macro NOW */
  481.         }
  482.     }
  483.     starttick = cticks + clickdelay;
  484.     while (myEvent.modifiers != shiftKey && starttick > cticks)
  485.         /* wait 1/6 sec to verify the user really wants to do a selection range */
  486.         ;
  487.         
  488.     while (StillDown()) {
  489.         /* highlight selection range for copy */
  490.         
  491.         if (keydp->selfirsttime) {
  492.              if ( (myEvent.modifiers == shiftKey) || doubleclick) {
  493.                 /* the user wants to set a selection range from the cursor */
  494.                 
  495.                 if (trackon && !donttrack) {
  496.                     InvertRect(&mouserect);    /* blank old track rectangle */
  497.                     trackon = FALSE;
  498.                 }
  499.                 
  500.                 keydp->selfirsttime = FALSE;
  501.                 nomove = FALSE;
  502.                 if (!keydp->selrectset) {
  503.                     /* set beginning point */
  504.                     keydp->selystart = keydp->ypos;
  505.                     keydp->selxstart = keydp->xpos;
  506.                     keydp->selyend = keydp->ypos;
  507.                     keydp->selxend = keydp->xpos;
  508.                     selmake(yloc, xloc);
  509.                 }
  510.                 else
  511.                     seladd(yloc, xloc);
  512.             }
  513.             else {
  514.                 if (keydp->selrectset)
  515.                     /* clear any existing selection */
  516.                     selreset(keydp);
  517.                     
  518.                 /* set beginning point at first point */
  519.                 keydp->selystart = yloc;
  520.                 keydp->selxstart = xloc;
  521.                 keydp->selyend = yloc;
  522.                 keydp->selxend = xloc;
  523.             }
  524.             keydp->selfirsttime = FALSE;
  525.         }
  526.  
  527.         GetMouse(&newmouse);
  528.         nyloc = newmouse.v / keydp->lineheight;
  529.         nxloc = newmouse.h / keydp->fontwidth;
  530.         
  531.         /* fix the x,y range within the screen */
  532.         if (nyloc > keydp->lastrow) {
  533.             nyloc = keydp->lastrow + 1;
  534.             nxloc = 0;
  535.         }
  536.         else if (nyloc < 0)
  537.             nyloc = 0;
  538.         if (nxloc > keydp->lastcol) {
  539.             nyloc++;
  540.             nxloc = 0;
  541.         }
  542.         else if (nxloc < 0)
  543.             nxloc = 0;
  544.         
  545.         if (nyloc != oyloc || nxloc != oxloc) {
  546.             /* cursor moved, extend selection */
  547.             nomove = FALSE;
  548.             
  549.             if (trackon && !donttrack) {
  550.                 InvertRect(&mouserect);    /* blank old track rectangle */
  551.                 trackon = FALSE;
  552.             }
  553.             if (keydp->selrectset)
  554.                 selmove(nyloc, nxloc);
  555.             else {
  556.                 selmake(nyloc, nxloc);
  557.             }
  558.         }
  559.         oxloc = nxloc;
  560.         oyloc = nyloc;
  561.     }
  562.     if (nomove && !doubleclick) {
  563.         /* the user wants to move the cursor */
  564.         /* only move the cursor if mouse is in same position */
  565.  
  566.         selreset(keydp);
  567.         if (keydp->connopen) {
  568.             keyputaction(RSLT_YCURS, yloc);
  569.             keyputaction(RSLT_XCURS, xloc);
  570.         }
  571.     }
  572.     selmenuitems(keydp);
  573.         /* fix menu items to reflect whether user has a selection range */
  574. }
  575.  
  576. /* set the current selection range given two new points */
  577.     
  578. selmake(yloc, xloc)
  579. {
  580.     /* make a fresh selection from the default position;
  581.         start == end */
  582.     keydp->starty = keydp->selystart;
  583.     keydp->startx = keydp->selxstart;
  584.     if (yloc < keydp->selystart) {
  585.         /* selection extends up */
  586.         selset(yloc, xloc, keydp->selystart, keydp->selxstart);
  587.     }
  588.     else if (yloc > keydp->selystart) {
  589.         /* selection extends down */
  590.         selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  591.     }
  592.     else {
  593.         /* selection on one line */
  594.         if (keydp->selxstart < xloc) {
  595.             /* extend right */
  596.             selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  597.         }
  598.         else {
  599.             /* extend left */
  600.             selset(yloc, xloc, keydp->selystart, keydp->selxstart);
  601.         }
  602.     }
  603.     selinvert(keydp);
  604.     keydp->selrectvis = TRUE;
  605. }
  606.  
  607. /* Shift-extend the current selection range given two new points */
  608.     
  609. seladd(yloc, xloc) 
  610. {
  611.     if (yloc < keydp->selystart) {
  612.         /* extend selection  up */
  613.         selextend(yloc, xloc, keydp->selystart, keydp->selxstart);
  614.         selset(yloc, xloc, keydp->selyend, keydp->selxend);
  615.         keydp->starty = keydp->selyend;
  616.         keydp->startx = keydp->selxend;
  617.     }
  618.     else if (yloc > keydp->selyend) {
  619.         /* extend selection down */
  620.         selextend(keydp->selyend, keydp->selxend, yloc, xloc);
  621.         selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  622.         keydp->starty = keydp->selystart;
  623.         keydp->startx = keydp->selxstart;
  624.     }
  625.     else {
  626.         /* we shrink the selection up */
  627.         if (keydp->selystart == keydp->selyend) {
  628.             /* just one line, always extend if outside range, else shrink right */
  629.             if (xloc < keydp->selxstart) {
  630.                 /* expand selection left */
  631.                 selextend(yloc, xloc, keydp->selystart, keydp->selxstart);
  632.                 selset(yloc, xloc, keydp->selyend, keydp->selxend);
  633.                 keydp->starty = keydp->selyend;
  634.                 keydp->startx = keydp->selxend;
  635.             }
  636.             else if (xloc > keydp->selxend) {
  637.                 /* expand right */
  638.                 selextend(keydp->selyend, keydp->selxend, yloc, xloc);
  639.                 selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  640.                 keydp->starty = keydp->selystart;
  641.                 keydp->startx = keydp->selxstart;
  642.             }
  643.             else {
  644.                 /* shrink right */
  645.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  646.                 selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  647.                 keydp->starty = keydp->selystart;
  648.                 keydp->startx = keydp->selxstart;
  649.             }
  650.         }
  651.         else if (yloc == keydp->selystart) {
  652.             /* on same line as x, which pair is last? */
  653.             if (xloc > keydp->selxstart) {
  654.                 /* shrink selection on the right */
  655.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  656.                 selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  657.                 keydp->starty = keydp->selystart;
  658.                 keydp->startx = keydp->selxstart;
  659.             }
  660.             else if (xloc < keydp->selxstart) {
  661.                 /* expand selection left */
  662.                 selextend(yloc, xloc, keydp->selystart, keydp->selxstart);
  663.                 selset(yloc, xloc, keydp->selyend, keydp->selxend);
  664.                 keydp->starty = keydp->selyend;
  665.                 keydp->startx = keydp->selxend;
  666.             }
  667.             else {
  668.                 /* same old selection */
  669.                 keydp->starty = keydp->selyend;
  670.                 keydp->startx = keydp->selxend;
  671.                 return;
  672.             }
  673.         }
  674.         else if (yloc == keydp->selyend) {
  675.             /* on same line as x, which pair is last? */
  676.             if (xloc > keydp->selxend) {
  677.                 /* extend selection right */
  678.                 selextend(keydp->selyend, keydp->selxend, yloc, xloc);
  679.             }
  680.             else if (xloc < keydp->selxend) {
  681.                 /* shrink selection from right */
  682.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  683.             }
  684.             selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  685.             keydp->starty = keydp->selystart;
  686.             keydp->startx = keydp->selxstart;
  687.         }
  688.         else {
  689.             /* always shrink bottom */
  690.             selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  691.             selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  692.             keydp->starty = keydp->selystart;
  693.             keydp->startx = keydp->selxstart;
  694.         }
  695.     }
  696. }
  697.  
  698. /* dynamically extend the current selection range given two new points--
  699.     centers around beginning point, which is always start or end of selection */
  700.     
  701. selmove(yloc, xloc) 
  702. {
  703.     if (keydp->starty == keydp->selystart && keydp->startx == keydp->selxstart) {
  704.         /* anchor is at beginning of selection */
  705.         if (yloc < keydp->selystart) {
  706.             /* selection shifts up around anchor */
  707.             selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  708.             selset(yloc, xloc, keydp->selystart, keydp->selxstart);
  709.         }
  710.         else if (yloc > keydp->selyend) {
  711.             /* extend selection down */
  712.             selextend(keydp->selyend, keydp->selxend, yloc, xloc);
  713.             selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  714.         }
  715.         else if (keydp->selystart == keydp->selyend) {
  716.             /* just one line, always extend if outside range, else shrink right */
  717.             if (xloc <= keydp->selxstart) {
  718.                 /* selection shifts up around anchor */
  719.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  720.                 selset(yloc, xloc, keydp->selystart, keydp->selxstart);
  721.             }
  722.             else if (xloc > keydp->selxend) {
  723.                 /* expand right */
  724.                 selextend(keydp->selyend, keydp->selxend, yloc, xloc);
  725.                 selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  726.             }
  727.             else {
  728.                 /* in the middle, shrink right end */
  729.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  730.                 selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  731.             }
  732.         }
  733.         else if (yloc == keydp->selystart) {
  734.             /* on same line as x, which pair is last? */
  735.             if (xloc >= keydp->selxstart) {
  736.                 /* shrink selection on the right */
  737.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  738.                 selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  739.             }
  740.             else if (xloc < keydp->selxstart) {
  741.                 /* selection shifts up around anchor */
  742.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  743.                 selset(yloc, xloc, keydp->selystart, keydp->selxstart);
  744.             }
  745.             else
  746.                 /* same old selection */
  747.                 return;
  748.         }
  749.         else if (yloc == keydp->selyend) {
  750.             /* on same line as x, which pair is last? */
  751.             if (xloc > keydp->selxend) {
  752.                 /* extend selection right */
  753.                 selextend(keydp->selyend, keydp->selxend, yloc, xloc);
  754.             }
  755.             else if (xloc < keydp->selxend) {
  756.                 /* shrink selection from right */
  757.                 selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  758.             }
  759.             else
  760.                 /* same old selection */
  761.                 return;
  762.             selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  763.         }
  764.         else {
  765.             /* somewhere in the middle of the selection, shrink bottom */
  766.             selextend(yloc, xloc, keydp->selyend, keydp->selxend);
  767.             selset(keydp->selystart, keydp->selxstart, yloc, xloc);
  768.         }
  769.     }
  770.     else if (keydp->starty == keydp->selyend && keydp->startx == keydp->selxend) {
  771.         /* anchor is at end of selection */
  772.         if (yloc < keydp->selystart) {
  773.             /* extend selection  up */
  774.             selextend(yloc, xloc, keydp->selystart, keydp->selxstart);
  775.             selset(yloc, xloc, keydp->selyend, keydp->selxend);
  776.         }
  777.         else if (yloc > keydp->selyend) {
  778.             /* shift selection around anchor */
  779.             selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  780.             selset(keydp->selyend, keydp->selxend, yloc, xloc);
  781.         }
  782.         else if (keydp->selystart == keydp->selyend) {
  783.             /* just one line, always extend if outside range, else shrink right */
  784.             if (xloc <= keydp->selxstart) {
  785.                 /* expand left */
  786.                 selextend(yloc, xloc, keydp->selystart, keydp->selxstart);
  787.                 selset(yloc, xloc, keydp->selyend, keydp->selxend);
  788.             }
  789.             else if (xloc > keydp->selxend) {
  790.                 /* shift selection around anchor */
  791.                 selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  792.                 selset(keydp->selyend, keydp->selxend, yloc, xloc);
  793.             }
  794.             else {
  795.                 /* in the middle, shrink left */
  796.                 selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  797.                 selset(yloc, xloc, keydp->selyend, keydp->selxend);
  798.             }
  799.         }
  800.         else if (yloc == keydp->selystart) {
  801.             /* on same line as x, which pair is last? */
  802.             if (xloc > keydp->selxstart) {
  803.                 /* shrink selection on the left */
  804.                 selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  805.             }
  806.             else if (xloc < keydp->selxstart) {
  807.                 /* expand selection left */
  808.                 selextend(yloc, xloc, keydp->selystart, keydp->selxstart);
  809.             }
  810.             else
  811.                 /* same old selection */
  812.                 return;
  813.             selset(yloc, xloc, keydp->selyend, keydp->selxend);
  814.         }
  815.         else if (yloc == keydp->selyend) {
  816.             /* on same line as x, which pair is last? */
  817.             if (xloc < keydp->selxend) {
  818.                 /* shrink left */
  819.                 selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  820.                 selset(yloc, xloc, keydp->selyend, keydp->selxend);
  821.             }
  822.             else if (xloc > keydp->selxend) {
  823.                 /* shift selection around anchor */
  824.                 selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  825.                 selset(keydp->selyend, keydp->selxend, yloc, xloc);
  826.             }
  827.         }
  828.         else {
  829.             /* in middle, shrink top */
  830.             selextend(keydp->selystart, keydp->selxstart, yloc, xloc);
  831.             selset(yloc, xloc, keydp->selyend, keydp->selxend);
  832.         }
  833.     }
  834. }
  835.  
  836. /* sets the selection range markers and rectangles */
  837.  
  838. selset(yloc, xloc, ypos, xpos)
  839. {
  840.     int midcount;
  841.     
  842.     keydp->selrectset = TRUE;
  843.     keydp->seltopset = FALSE;
  844.     keydp->selmidset = FALSE;
  845.     keydp->selbotset = FALSE;
  846.  
  847.     keydp->selystart = yloc;
  848.     keydp->selyend = ypos;
  849.     keydp->selxstart = xloc;
  850.     keydp->selxend = xpos;
  851.  
  852.     if (yloc == ypos) {
  853.         /* set on a single line */
  854.         
  855.         keydp->seltoprect.top = ypos * keydp->lineheight + keydp->voffset;
  856.         keydp->seltoprect.bottom = keydp->seltoprect.top + keydp->lineheight;
  857.         keydp->seltoprect.left = keydp->selxstart * keydp->fontwidth + keydp->hoffset;
  858.         keydp->seltoprect.right = keydp->seltoprect.left + (keydp->selxend - keydp->selxstart) * keydp->fontwidth;
  859.         keydp->seltopset = TRUE;
  860.     }
  861.     else {
  862.         /* invert the top rectangle */
  863.         keydp->seltoprect.top = yloc * keydp->lineheight + keydp->voffset;
  864.         keydp->seltoprect.bottom = keydp->seltoprect.top + keydp->lineheight;
  865.         keydp->seltoprect.left = xloc * keydp->fontwidth + keydp->hoffset;
  866.         keydp->seltoprect.right = keydp->rightmarg;
  867.         keydp->seltopset = TRUE;
  868.         
  869.         /* invert the mid rectangle if necessary */
  870.         if ( (midcount = ypos - yloc - 1) >= 1) {
  871.             keydp->selmidrect.top = keydp->seltoprect.top + keydp->lineheight + keydp->voffset;
  872.             keydp->selmidrect.bottom = keydp->selmidrect.top + midcount * keydp->lineheight;
  873.             keydp->selmidrect.left = keydp->hoffset;
  874.             keydp->selmidrect.right = keydp->rightmarg;
  875.             keydp->selmidset = TRUE;
  876.         }
  877.         
  878.         /* invert the bottom rectangle */
  879.         keydp->selbotrect.top = ypos * keydp->lineheight + keydp->voffset;
  880.         keydp->selbotrect.bottom = keydp->selbotrect.top + keydp->lineheight;
  881.         keydp->selbotrect.left = keydp->hoffset;
  882.         keydp->selbotrect.right = (xpos) * keydp->fontwidth + keydp->hoffset;
  883.         keydp->selbotset = TRUE;
  884.     }
  885. }
  886.  
  887. /* invert the new portions of a selection */
  888.  
  889. selextend(yloc, xloc, ypos, xpos)
  890. {
  891.     int midcount;
  892.     Rect trect;
  893.     int txstart;
  894.     int txend;
  895.  
  896.     if (yloc == ypos) {
  897.         /* set on a single line */
  898.         txstart = xloc;
  899.         txend = xpos;
  900.         
  901.         trect.top = ypos * keydp->lineheight + keydp->voffset;
  902.         trect.bottom = trect.top + keydp->lineheight;
  903.         trect.left = txstart * keydp->fontwidth + keydp->hoffset;
  904.         trect.right = trect.left + (txend - txstart) * keydp->fontwidth;
  905.         SETHILITE();
  906.         InvertRect(&trect);
  907.     }
  908.     else {
  909.         /* invert the top rectangle */
  910.         trect.top = yloc * keydp->lineheight + keydp->voffset;
  911.         trect.bottom = trect.top + keydp->lineheight;
  912.         trect.left = xloc * keydp->fontwidth + keydp->hoffset;
  913.         trect.right = keydp->rightmarg;
  914.         SETHILITE();
  915.         InvertRect(&trect);
  916.         
  917.         /* invert the mid rectangle if necessary */
  918.         if ( (midcount = ypos - yloc - 1) >= 1) {
  919.             trect.top = trect.top + keydp->lineheight + keydp->voffset;
  920.             trect.bottom = trect.top + midcount * keydp->lineheight;
  921.             trect.left = keydp->hoffset;
  922.             trect.right = keydp->rightmarg;
  923.             SETHILITE();
  924.             InvertRect(&trect);
  925.         }
  926.         
  927.         /* invert the bottom rectangle */
  928.         trect.top = ypos * keydp->lineheight + keydp->voffset;
  929.         trect.bottom = trect.top + keydp->lineheight;
  930.         trect.left = keydp->hoffset;
  931.         trect.right = (xpos) * keydp->fontwidth + keydp->hoffset;
  932.         SETHILITE();
  933.         InvertRect(&trect);
  934.     }
  935. }
  936.  
  937.  
  938. selinvert(twp)
  939. struct winds * twp;
  940. {
  941.     if (keydp->seltopset) {
  942.         SETHILITE();
  943.         InvertRect(&twp->seltoprect);
  944.     }
  945.     if (keydp->selmidset) {
  946.         SETHILITE();
  947.         InvertRect(&twp->selmidrect);
  948.     }
  949.     if (keydp->selbotset) {
  950.         SETHILITE();
  951.         InvertRect(&twp->selbotrect);
  952.     }
  953. }
  954.  
  955. selreset(twp)
  956. struct winds * twp;
  957. {
  958.     if (twp->selrectvis) {
  959.         selinvert(twp);
  960.     }
  961.     twp->selrectset = FALSE;
  962.     twp->selrectvis = FALSE;
  963.     twp->seltopset = FALSE;
  964.     twp->selmidset = FALSE;
  965.     twp->selbotset = FALSE;
  966.     twp->selystart = 0;
  967.     twp->selxstart = 0;
  968.     twp->selyend = 0;
  969.     twp->selxend = 0;
  970. }
  971.  
  972.  
  973. /* work the controls at the top of the emulator screen */
  974.  
  975. doq1controls(where)
  976. Point * where;
  977. {
  978.     Point thepoint;
  979.     ControlHandle whichcontrol;
  980.     struct fontsave ofont;
  981.     
  982.     if (!keydp->connopen)
  983.         return;
  984.         
  985.     thepoint.h = where->h;
  986.     thepoint.v = where->v;
  987.     
  988.     if (FindControl(pass(thepoint), keydp->emwindow, &whichcontrol)) {
  989.         savefont(&ofont);
  990.         if (TrackControl(whichcontrol, pass(thepoint), (ProcPtr) NULL)) {
  991.             if (keydp->ibm_keymode) {
  992.                 switch ( (int) (*whichcontrol)->contrlRfCon) {
  993.                     case Q1BUT1: {
  994.                         keyputaction(RSLT_PFKY,ENTER);
  995.                         break;
  996.                     }
  997.                     case Q1BUT2: {
  998.                         keyputaction(RSLT_PFKY,PA1);
  999.                         break;
  1000.                     }
  1001.                     case Q1BUT3: {
  1002.                         keyputaction(RSLT_PFKY,PA2);
  1003.                         break;
  1004.                     }
  1005.                     case Q1BUT4: {
  1006.                         keyputaction(RSLT_PFKY,CLEAR);
  1007.                         break;
  1008.                     }
  1009.                     case Q1BUT5: {
  1010.                         /* insert */
  1011.                         keyputaction(RSLT_LCAC,INSRT);
  1012.                         break;
  1013.                     }
  1014.                     case Q1BUT6: {
  1015.                         /* reset */
  1016.                         sendReset();
  1017.                         break;
  1018.                     }
  1019.                     case Q1BUT7: {
  1020.                         /* home */
  1021.                         keyputaction(RSLT_MVCR,HOME);
  1022.                         break;
  1023.                     }
  1024.                     case Q1BUT8: {
  1025.                         /* erase input */
  1026.                         keyputaction(RSLT_LCAC,INPUT_ERASE);
  1027.                         /* TODO not defined in 7171keys document */
  1028.                         break;
  1029.                     }
  1030.                     case Q1BUT9: {
  1031.                         keyputaction(RSLT_LCAC,ERASE_EOF);
  1032.                         /* erase to end of field */
  1033.                         break;
  1034.                     }
  1035.                     case Q1BUT10: {
  1036.                         keyputaction(RSLT_PFKY,PA3);
  1037.                         /* PA3 */
  1038.                         break;
  1039.                     }
  1040.                     case Q1BUT11: {
  1041.                         keyputaction(RSLT_LCAC,DEL_CHAR);
  1042.                         /* delete char */
  1043.                         break;
  1044.                     }
  1045.                 }
  1046.             }
  1047.             else {
  1048.                 switch ( (int) (*whichcontrol)->contrlRfCon) {
  1049.                     case Q1CR: {
  1050.                         /* CR */
  1051.                         keyputaction(RSLT_ASCI, CR);
  1052.                         break;
  1053.                     }
  1054.                     case Q1LF: {
  1055.                         /* send linefeed */
  1056.                         keyputaction(RSLT_ASCI, LF);
  1057.                         break;
  1058.                     }
  1059.                     case Q1ESC: {
  1060.                         /* send escape */
  1061.                         keyputaction(RSLT_ASCI, ESC);
  1062.                         break;
  1063.                     }
  1064.                     case Q1CTLS: {
  1065.                         /* send ^S */
  1066.                         keyputaction(RSLT_ASCI, CTLS);
  1067.                         HiliteControl(keydp->q1controls[Q1CTLS], 1); 
  1068.                         break; 
  1069.                     }
  1070.                     case Q1CTLQ: {
  1071.                         /* send ^Q */
  1072.                         keyputaction(RSLT_ASCI, CTLQ);
  1073.                         HiliteControl(keydp->q1controls[Q1CTLS], 0); 
  1074.                         break;
  1075.                     }
  1076.                     case Q1DEL: {
  1077.                         /* Delete */
  1078.                         keyputaction(RSLT_ASCI, DELETE);
  1079.                         break;
  1080.                     }
  1081.                     case Q1BREAK:  {
  1082.                         /* send BREAK */
  1083.                         sendBreak();
  1084.                         break;
  1085.                     }
  1086.                     case Q1CTLC: {
  1087.                         /* ^C */
  1088.                         keyputaction(RSLT_ASCI, CTLC);
  1089.                         break;
  1090.                     }
  1091.                     case Q1CTLU: {
  1092.                         /* ^U */
  1093.                         keyputaction(RSLT_ASCI, CTLU);
  1094.                         break;
  1095.                     }
  1096.                     case Q1IC: {
  1097.                         /* ^U */
  1098.                         keyputaction(RSLT_ASCI, ESC);
  1099.                         keyputaction(RSLT_ASCI, 'O');
  1100.                         keyputaction(RSLT_ASCI, 'w');
  1101.                         break;
  1102.                     }
  1103.                     case Q1DC: {
  1104.                         /* ^U */
  1105.                         keyputaction(RSLT_ASCI, ESC);
  1106.                         keyputaction(RSLT_ASCI, 'O');
  1107.                         keyputaction(RSLT_ASCI, 'y');
  1108.                         break;
  1109.                     }
  1110.                 }
  1111.             }
  1112.         }
  1113.         restorefont(&ofont);
  1114.     }
  1115. }
  1116.  
  1117.  
  1118. /* 
  1119.  * when a third quadrant button is pushed, this routine is called to 
  1120.  * send a string to the host.
  1121.  */
  1122.  
  1123. doq3controls()
  1124. {
  1125.     register char * charp;
  1126.     long ticks;
  1127.     short shift = FALSE;
  1128.  
  1129.     if (!keydp->connopen)
  1130.         return(-1);
  1131.         
  1132.     if (!q3button)
  1133.         return(-1);
  1134.         
  1135.     FillRoundRect(&q3highrect, BUT3HIGH, BUT3WIDE, gray);
  1136.     
  1137.     if (keydp->ibm_keymode) {
  1138.         if (myEvent.modifiers & shiftKey)
  1139.             /* do a shift */
  1140.             keyputaction(RSLT_PFKY, PFSHIFT);
  1141.         keyputaction(RSLT_PFKY, PF1 + q3button - 1);
  1142.     }
  1143.     else {
  1144.         if (myEvent.modifiers & shiftKey)
  1145.             /* do a shift */
  1146.             shift = 12;
  1147.             
  1148.         if (keydp->termtype == TERM_VT100
  1149.             || keydp->termtype == TERM_VT102
  1150.             || keydp->termtype == TERM_VT220
  1151.         ) {
  1152.             /* vt100 strings */
  1153.             if (shift && q3button > 6) {
  1154.                 /* one of the 6 VT102 function keys */
  1155.                 sendvt102key(q3vtcontrols[q3button + shift - 1]);
  1156.             }
  1157.             else
  1158.                 sendvtkeyfunc(q3vtcontrols[q3button + shift - 1]);
  1159.         }
  1160.         else {
  1161.             /* send H19 control string */
  1162.             keyputaction(RSLT_ASCI, 0x1B);
  1163.             keyputaction(RSLT_ASCI, q3controls[q3button - 1]);
  1164.         }
  1165.     }
  1166.     Delay( (long) 10, &ticks);
  1167.     FillRoundRect(&q3highrect, BUT3HIGH, BUT3WIDE, black);
  1168.     blanklabels();
  1169. }
  1170.  
  1171.  
  1172.  
  1173. /*    this routine uses the same logic used for drawing the left hand controls
  1174.     to check to see if they should be highlighted
  1175. */
  1176.  
  1177. check3controls(mouseloc, shift)
  1178. Point mouseloc;
  1179. int shift;
  1180. {
  1181.     register int count;
  1182.     Rect fillrect;
  1183.  
  1184.     fillrect.top = 0;
  1185.     fillrect.left = -12;
  1186.     fillrect.bottom = 21;    /* bottom - top == 20, * 12 boxes == height of window */
  1187.     fillrect.right = -2;    /* was -4 */
  1188.  
  1189.     for (count = 1; count < 13; count++) {
  1190.         if (PtInRect(pass(mouseloc), &fillrect)) {
  1191.             if (q3button) { 
  1192.                 if (q3highrect.top == fillrect.top) {
  1193.                     /* don't bother filling it again */
  1194. #ifdef WORONACURSOR
  1195.                     if (shift != labelshift)
  1196.                         SetCursor(*GetCursor(127 + count + shift));
  1197.                             /* update the numbered cursor */
  1198. #endif
  1199.                     return;
  1200.                 }
  1201.                 else if (q3highrect.top != -1) {
  1202.                     /* the old one needs to be set back to gray */
  1203.                     FillRoundRect(&q3highrect, (short) BUT3HIGH, (short) BUT3WIDE, gray);
  1204.                     FrameRect(&q3highrect);
  1205.                 }
  1206.             }
  1207.             q3button = count;
  1208.             q3highrect.top = fillrect.top;
  1209.             q3highrect.left = fillrect.left + 3;
  1210.             q3highrect.bottom = fillrect.bottom;
  1211.             q3highrect.right = fillrect.right - 2;
  1212.             FillRoundRect(&q3highrect, (short) BUT3HIGH, (short) BUT3WIDE, black);
  1213.  
  1214. #ifdef WORONACURSOR
  1215.             SetCursor(*GetCursor(127 + count + shift));
  1216.                 /* put up a numbered cursor to show which PF is activated */
  1217. #endif
  1218.             return;
  1219.         }
  1220.         if (count % 3) {
  1221.             fillrect.top += q3conth;
  1222.             fillrect.bottom += q3conth;
  1223.         }
  1224.         else {
  1225.             fillrect.top += q3conth + q3contskip;
  1226.             fillrect.bottom += q3conth + q3contskip;
  1227.         }
  1228.     }
  1229. #ifdef WORONACURSOR
  1230.     if (!q3button)
  1231.         /* make the cursor an arrow if no button has been selected yet */
  1232. #endif
  1233.         SetCursor(&arrow);
  1234. }
  1235.  
  1236.  
  1237. reset3controls()
  1238. {
  1239.     if (q3button) {
  1240.         FillRoundRect(&q3highrect, (short) BUT3HIGH, (short) BUT3WIDE, gray);
  1241.         FrameRect(&q3highrect);
  1242.  
  1243.         q3highrect.top = -1;        
  1244.         q3button = 0;
  1245.     }
  1246. }
  1247.  
  1248.  
  1249. /* draw labels to the right of the buttons in the third quadrant */
  1250.  
  1251. q3labels(shift)
  1252. int shift;        /* + 12 when Shift key down */
  1253. {
  1254.     Point penloc;
  1255.     int count;
  1256.     int length;            /* length of a string */
  1257.     int maxlength;        /* length of the longest string */
  1258.     int asciishift;
  1259.     struct fontsave ofont;
  1260.     
  1261.     maxlength = 0;
  1262.     
  1263.     if (q3labdrawn) {
  1264.         if (shift == labelshift)
  1265.             /* already displayed correctly */
  1266.             return(0);
  1267.     }
  1268.     /* first find the longest string to size the box... */
  1269.     asciishift = (keydp->ibm_keymode ? 0 : 24);
  1270.         /* use VT100 labels if in ASCII mode */
  1271.         
  1272.     if (q3labdrawn) {
  1273.         /* reset clip so we can draw in box */
  1274.         ClipRect(&boxrect);
  1275.     }
  1276.     else {
  1277.         emwdeactivate();                /* will increment bkrd_act */
  1278.         InvertRect(&keydp->qmarkrect);
  1279.         
  1280.         for (count = 0; count < 24; count++) {
  1281.             if (q3strings[count + asciishift] == NULL)
  1282.                 /* make sure the string exists! */
  1283.                 continue;
  1284.             length = strlen(q3strings[count + asciishift]);
  1285.             if (length > maxlength)
  1286.                 maxlength = length;
  1287.         }
  1288.         boxrect.top = -4;
  1289.         boxrect.left = -2;
  1290.         boxrect.bottom = 285;
  1291.         boxrect.right = maxlength * 6 + 20;
  1292.             /* set to length of largest string  +20--assuming fixed-width font */
  1293.     }
  1294.     
  1295.     EraseRect(&boxrect);
  1296.     FrameRect(&boxrect);
  1297.  
  1298.     penloc.h = 10;
  1299.     penloc.v = 15;
  1300.     
  1301.     savefont(&ofont);
  1302.     for (count = 1; count < 13; count++) {
  1303.         if (q3strings[count + shift + asciishift] == NULL)
  1304.             /* make sure the string exists! */
  1305.             continue;
  1306.         MoveTo(penloc.h, penloc.v);
  1307.         DrawText(q3strings[count + shift + asciishift - 1], (short) 0, 
  1308.             strlen(q3strings[count + shift + asciishift - 1]) );
  1309.         if (count % 3) {
  1310.             penloc.v += 22;
  1311.         }
  1312.         else {
  1313.             penloc.v += 29;
  1314.         }
  1315.     }
  1316.     restorefont(&ofont);
  1317.     
  1318.     if (!q3labdrawn) {
  1319.         /* now set the clip region to exclude boxrect so no drawing can occur in box */
  1320.         /* NB if bkrd_act does not disable cursor blink turds will result */
  1321.         
  1322.         GetClip(emclip);
  1323.         RectRgn(q3clip, &boxrect);
  1324.         DiffRgn(emclip, q3clip, q3clip);
  1325.         SetClip(q3clip);
  1326.     }
  1327.     else
  1328.         SetClip(q3clip);    /* reset clip */
  1329.     
  1330.     q3labdrawn = keydp->emwindow;    
  1331. }
  1332.  
  1333.  
  1334. /* blank the pf key labels in the 3rd quadrant */
  1335.  
  1336. blanklabels()
  1337. {
  1338.     GrafPtr oport;
  1339.  
  1340.     if (q3labdrawn) {
  1341.         GetPort(&oport);
  1342.         SetPort(q3labdrawn);
  1343.         
  1344.         --bkrd_act;
  1345.         SetClip(emclip);                /* restore portRect clip */
  1346.         EraseRect(&boxrect);
  1347.         InvertRect(&keydp->qmarkrect);
  1348.         InvalRect(&boxrect);
  1349.         
  1350.         SetPort(oport);
  1351.         q3labdrawn = NULL;
  1352.     }
  1353. }
  1354.  
  1355.  
  1356.  
  1357. showq3buttons()
  1358. {
  1359.     Rect fillrect;
  1360.     int count;
  1361.     
  1362.     fillrect.top = 0;
  1363.     fillrect.left = -9;
  1364.     fillrect.bottom = 21;    
  1365.     fillrect.right = -4;
  1366.  
  1367.     for (count = 1; count < 13; count++) {
  1368.         FillRoundRect(&fillrect, (short) BUT3HIGH, (short) BUT3WIDE, gray);
  1369.         FrameRect(&fillrect);
  1370.         if (count % 3) {
  1371.             fillrect.top += q3conth;
  1372.             fillrect.bottom += q3conth;
  1373.         }
  1374.         else {
  1375.             fillrect.top += q3conth + q3contskip;
  1376.             fillrect.bottom += q3conth + q3contskip;
  1377.         }
  1378.     }
  1379. }
  1380.  
  1381.  
  1382. /* the following are different because the use emdp rather than keydp */
  1383.  
  1384.  
  1385. /* highlight the iconwindow contents to show that new data has arrived */
  1386.  
  1387. emalert()
  1388. {
  1389.     GrafPtr oldport;
  1390.     Rect destrect;
  1391.     
  1392.     destrect.top = 0;
  1393.     destrect.left = 0;
  1394.     destrect.bottom = 33;
  1395.     destrect.right = 46;
  1396.     
  1397.     if (!emdp->iconhigh && emdp->icon_up) {
  1398.         GetPort(&oldport);
  1399.         SetPort(emdp->iconwindow);
  1400.         SETHILITE();
  1401.         InvertRect(&destrect);
  1402.         emdp->iconhigh = TRUE;
  1403.         SetPort(oldport);
  1404.     }
  1405. }
  1406.  
  1407.  
  1408. /* TODO is DANGEROUS assumes keywindow is active */
  1409.  
  1410.  
  1411. /* light up INSERT button when in IBM mode */
  1412.  
  1413. showinsert()
  1414. {
  1415.     struct fontsave ofont;
  1416.     
  1417.     if (emdp->emwindow == NULL)
  1418.         return;
  1419.         
  1420.     if (emdp->ibm_keymode && emdp->q1controls[Q1BUT5] != NULL) {
  1421.         savefont(&ofont);
  1422.         HiliteControl(emdp->q1controls[Q1BUT5], (short) 1);
  1423.         emdp->controlschanged = TRUE;
  1424.         copytoprect(emwindow);
  1425.         restorefont(&ofont);
  1426.     }
  1427. }
  1428.  
  1429.  
  1430. /* un-highlight INSERT button when in IBM mode */
  1431.  
  1432. clrinsert()
  1433. {
  1434.     struct fontsave  ofont;
  1435.     
  1436.     if (emdp->emwindow == NULL)
  1437.         return;
  1438.         
  1439.     if (emdp->ibm_keymode && emdp->q1controls[4] != NULL) {
  1440.         savefont(&ofont);
  1441.         HiliteControl(emdp->q1controls[4], (short) 0);
  1442.         emdp->controlschanged = TRUE;
  1443.         copytoprect(emwindow);
  1444.         restorefont(&ofont);
  1445.     }
  1446. }
  1447.  
  1448.  
  1449.